package org.metasketch.simulator.transformation.demo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.metasketch.demo.model.ActorRole;
import org.metasketch.demo.model.OrganizationalFunction;
import org.metasketch.demo.project.DEMOProject;
import org.metasketch.simulator.resources.Resource;
import org.metasketch.simulator.resources.ResourceBank;
import org.metasketch.simulator.resources.ResourceClass;

public class ResourceTransformer {

	public static void transform(DEMOProject project, ResourceBank resources) {

		List<ActorRole> internalRoles = GetValidElements
				.getValidActorRoles(project);

		List<ActorRole> externalRoles = GetValidElements
				.getValidExternalActorRoles(project);

		internalRoles.removeAll(externalRoles);

		List<Resource> externalRoleResources = new ArrayList<Resource>();
		Map<String, Resource> externalRolesPerIdentifier = new HashMap<String, Resource>();

		List<ResourceClass> internalRoleClasses = new ArrayList<ResourceClass>();
		Map<String, ResourceClass> internalRoleClassesPerIdentifier = new HashMap<String, ResourceClass>();

		List<Resource> internalOrgFunctions = new ArrayList<Resource>();
		Map<String, Resource> internalOrgFunctionsPerIdentifier = new HashMap<String, Resource>();

		// external roles are simple resources, in that they are integer
		// resources which will be managed by the engine.
		for (ActorRole actorRole : externalRoles) {
			Resource externalRole = new Resource();
			externalRole.setName(actorRole.getName());
			externalRole.setIdentifier(actorRole.getId());

			externalRoleResources.add(externalRole);
			externalRolesPerIdentifier.put(actorRole.getId(), externalRole);
		}

		// internal roles are resource classes
		for (ActorRole actorRole : internalRoles) {
			ResourceClass internalRole = new ResourceClass();
			internalRole.setName(actorRole.getName());
			internalRole.setIdentifier(actorRole.getId());

			internalRoleClasses.add(internalRole);
			internalRoleClassesPerIdentifier.put(actorRole.getId(),
					internalRole);
		}

		// internal roles are classes of resource which are the org functions,
		// which can be mapped to actual integer resources.
		for (ActorRole actorRole : internalRoles) {

			ResourceClass resourceClass = internalRoleClassesPerIdentifier
					.get(actorRole.getId());

			List<OrganizationalFunction> orgFunctions = GetValidElements
					.getOrgFunctions(project, actorRole);

			for (OrganizationalFunction organizationalFunction : orgFunctions) {

				Resource resource = internalOrgFunctionsPerIdentifier
						.get(organizationalFunction.getId());

				if (resource == null) {
					Resource internalOrgFunction = new Resource();
					internalOrgFunction.setRestorable(false);
					internalOrgFunction.setName(organizationalFunction
							.getName());
					internalOrgFunction.setIdentifier(organizationalFunction
							.getId());

					internalOrgFunctions.add(internalOrgFunction);
					internalOrgFunctionsPerIdentifier
							.put(organizationalFunction.getId(),
									internalOrgFunction);

					resource = internalOrgFunction;
				}

				// this is to stop duplications
				resource.addClass(resourceClass);
				resourceClass.addResource(resource);

			}

		}

		resources.getResources().addAll(internalOrgFunctions);
		resources.getResourceClasses().addAll(internalRoleClasses);
		resources.getResources().addAll(externalRoleResources);

		resources.getAttributes().put("internalOrgFunctions",
				internalOrgFunctions);
		resources.getAttributes().put("internalRoleClasses",
				internalRoleClasses);
		resources.getAttributes().put("externalRoleResources",
				externalRoleResources);

		resources.compile();

	}
}
